Typically, most objects created by a process are destroyed when that process terminates. A persistent object, however, is an object whose lifetime can exceed the lifetime of the process that creates or accesses the object. Object persistence is therefore a useful property for those objects instantiated in one process that carry information needed by other processes. For example, it may be desirable for one JAVA™ application to access the objects previously created by another Java application.
A first approach for implementing object persistence is to serialize the entire object into a structured sequence of bytes and store the serialized object into a file, a database, or other persistent object store. When the serialized object is needed by another process, the serialized object is deserialized back into a run-time object and used by that other process.
One drawback to this first approach is that it does not efficiently support the selective retrieval of persistent objects from the persistent object store. For example, a persistent object store may contain a plurality of employee objects, each identified by a name, social security number, and a position title. If an application wishes to retrieve all the software engineers from the persistent object store in accordance with this first approach, each employee object would have to deserialized back into a run-time object so that the object's position title field can be inspected to determine if the position title for the object is actually a software engineer. As a result, many objects are deserialized, which is an expensive operation, whether or not the objects are actually wanted.
Accordingly, a second approach has been developed to store persistent objects as rows in a database table, in which the columns of the database table correspond to fields of the persistent object. Since the fields of persistent object are stored in separate columns of the database table, these columns can be indexed and accessed by a database server so that the identifying which persistent objects satisfy a particular condition can be efficiently performed, e.g. by a B-Tree lookup. In the example, the persistent employee objects would be stored as rows in an employee table having one column for the name of the employee, another column for the social security number, and a third column for the position title. Thus, retrieving all the software engineers from among the persistent employee objects can be quickly performed simply by executing a “select” statement in the Structured Query Language (SQL) that uses an index built on the position title column. Consequently, the second approach promises to exploit the high-performance data storage and retrieval technology of modern database systems.
A major source of difficulty with conventional implementations of the second approach is due to an “impedance mismatch” in creating a direct object-relational mapping between the programming model and the database model. The programming model support a rich set of features for objects; for example, the programming model typically supports inheritance, polymorphism, multi-valued attributes, which are not easily handled in the database model. On the other hand, the database model employs concepts such as transaction semantics (commit, rollback), primary keys, foreign keys, uniqueness constraints, and other concepts that lack an immediate analog in the programming model. Therefore, the implementation of such a direct object-relational mapping involves much overhead.
Furthermore, the direct object-relational mapping is statically implemented for each class of object that may be persistent, adding persistence to the class interface. Thus, the overhead for implementing persistence in each class is incurred again and again for each new class. In addition, the direct object-relation mapping is fixed at compile-time, so that any changes made to the class must be reflected in re-coding the implementation of persistence for the class.
Attempts have been made to provide the implementation of persistence in a “persistent object” base class. Thus, the programmer designing the classes for persistent objects must derive these class from the persistent object base class. In single-inheritance languages such as JAVA™, however, this attempt compels the programmer to derive almost every class from the persistent object base class, which adds persistence to the interface of all of such classes, even if unneeded for particular classes, just to permit the use of polymorphism. Another attempt to reduce the programming overhead is by special pre-processing or post-processing of non-persistent classes to make the instances of the classes persistent. However, such pre-processing and post-processing greatly complicates the maintenance of the software and creates further opportunities for error when the pre-processing and post-processing are not consistently applied.
Therefore, there is a need for reducing the overhead and difficulties associated implementing persistence for objects of many different classes whose fields are to be stored in corresponding columns of a database, and whose structure may change over time (schema evolution).